.ball-box {
  width: 60rpx;
  height: 60rpx;
  border-radius: 100%;
  position: fixed;
  z-index: 1000;
  left: var(--startX);
  top: var(--startY);
  background-color: red;
  overflow: hidden;
}

/* 动画样式 */
.animation-ball {
  animation-fill-mode: forwards;
  animation: throwTopY 0.2s cubic-bezier(0, 0.3, 0.3, 1) forwards, 
             throwDropY 0.3s cubic-bezier(0.7, 0, 1, 0.7) 0.2s forwards,
             throwX 0.46s linear forwards, 
             showAndHide 0.6s linear forwards;
}

// y轴位移：小球先有一小段的上升，上升到最高点，这一段y轴位移一直在增加，我们给它动画叫做throwTopY,接下来抛物线下降，这个过程y轴一直在减少，一直减少到我们终点为止，我们叫做throwDropY
@keyframes throwTopY {
  0% {
    top: var(--startY);
  }
  100% {
    top: calc(var(--startY) - 120rpx);
  }
}

@keyframes throwDropY {
  0% {
    top: calc(var(--startY) - 120rpx);
  }
  100% {
    top: var(--endY);
  }
}

// x轴位移：小球x轴的位移在整个运动过程中都是从右向左变化的，我们认为一直是在线性变化的，我们动画称为throwX。
@keyframes throwX {
  0% {
    left: var(--startX);
  }
  100% {
    left: var(--endX);
  }
}

// 小球透明度：小球的透明度在初始阶段时候是能看到的，然后再接下来的过程是慢慢变成透明，直到完全透明，我们称showAndHide
@keyframes showAndHide {
  0% {
    opacity: 1;
  }
  90% {
    opacity: 0.9;
  }
  100% {
    opacity: 0;
  }
}